package com.ruoyi.net.utils;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.net.domain.ElementAlarm;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.*;

public class UdpTimerPollingWithTimeout {


    @Autowired
    private RedisCache redisCache;

    private static final String TARGET_IP = "10.20.1.44"; //"10.20.0.55";
    private static final int PORT = 7889;
    private static final int BUFFER_SIZE = 1024;
    private static final long POLLING_INTERVAL = 5000; // 轮询间隔，单位：毫秒
    private static final int TIMEOUT = 2000; // 接收数据的超时时间，单位：毫秒
    // 序列号  25 40
    private static Byte sno = 0;

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * Hex字符串转byte
     * @param inHex 待转换的Hex字符串
     * @return  转换后的byte
     */
    public static byte hexToByte(String inHex){
        return (byte)Integer.parseInt(inHex,16);
    }

    /**
     * hex字符串转byte数组
     * @param inHex 待转换的Hex字符串
     * @return  转换后的byte数组结果
     */
    public static byte[] hexToByteArray(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            //奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            //偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    public static void main(String[] args) {

        /*String hexString =
//                "8001000100" +  //5
//                "000000000000" + // 6
//                "00000001000d00000000" + //10
                "08001080808080081abf0108c1938004" +
                "108102180122b2010aa0010802101d1a" +
                "1d0006002f1869662d6e616d653d6d74" +
                "6e2d31306769302f312f302f31302000" +
                "2a79726f6c653d6d61696e2c706d3d4e" +
                "412c706769643d302c6c6d70646c6c6f" +
                "63616c6c696e6b69643d302c70656572" +
                "2d73656e642d69703d4e412c70656572" +
                "2d726563762d69703d4e412c6c6d7064" +
                "6c73656e6472656d6f74656c696e6b69" +
                "643d302c6c6d70646c7265637672656d" +
                "6f74656c696e6b69643d30120d08f310" +
                "1081bda9bc0618012000";*/

        String hexString =
//                "e4434ba4b832002a00001233080045c0" +
//                "012c2dd90000ff1177170a1400220a14" +
//                "00c71ed11ed10118" +
                        "000000c00001" +
                "00010000010446484d5002e302010000" +
                "007d000000f4" +
                "4a430422280000000000" +
                "7e000089c00100000000df8001000100" +
                "00000000000000000001000d00000000" +
                "08001080808080081abf0108c1938004" +
                "108102180122b2010aa0010802101d1a" +
                "1d0006002f1869662d6e616d653d6d74" +
                "6e2d31306769302f312f302f31302000" +
                "2a79726f6c653d6d61696e2c706d3d4e" +
                "412c706769643d302c6c6d70646c6c6f" +
                "63616c6c696e6b69643d302c70656572" +
                "2d73656e642d69703d4e412c70656572" +
                "2d726563762d69703d4e412c6c6d7064" +
                "6c73656e6472656d6f74656c696e6b69" +
                "643d302c6c6d70646c7265637672656d" +
                "6f74656c696e6b69643d30120d08f310" +
                "1081bda9bc0618012000";

        try {
            byte[] oriData = hexStringToByteArray(hexString);
            if (oriData.length >  28 + 21 + 21) {
                // 判断是否JC0422 【28,29，30,31】、报警数据【64,65】
                if (oriData[28] == (byte) 0x4a
                        && oriData[29] == (byte) 0x43
                        && oriData[30] == (byte) 0x04
                        && oriData[31] == (byte) 0x22
                        && oriData[64] == (byte) 0x00
                        && oriData[65] == (byte) 0x0d) {

                    // 处理接收到的数据
                    byte[] rData = new byte[oriData.length-(28 + 21 + 21)];
                    //从PB数据开始
                    System.arraycopy(oriData, (28 + 21 + 21), rData, 0, oriData.length-(28 + 21 + 21));
                    Alarm.NeAlarmHead neAlarmHead = Alarm.NeAlarmHead.parseFrom(rData);
                    System.out.println(neAlarmHead);
//                    neAlarmHead.getBrdAlrm(0).getArmVector(0).getArmValue(0).getCode();

                }
            }
            /*Alarm.NeAlarmHead neAlarmHead = Alarm.NeAlarmHead.parseFrom(rData);
            System.out.println(neAlarmHead);
            neAlarmHead.getBrdAlrm(0).getArmVector(0).getArmValue(0).getCode();
*/
            // 创建 DatagramSocket 并绑定源端口为 7889
            DatagramSocket socket = new DatagramSocket(PORT);
            socket.setSoTimeout(TIMEOUT);
            InetAddress targetAddress = InetAddress.getByName(TARGET_IP);
            // 启动定时任务
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    try {
                        // 要发送的数据
                        if (sno == Byte.MAX_VALUE) {
                            sno = Byte.MIN_VALUE;
                        } else {
                            sno = (byte) ((sno + 1) & 0xFF);
                        }

                        // 28 + 21
                        char[] bytes = {0x0, 0x0, 0x0, 0x4f, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x82, 0x46, 0x48, 0x4d, 0x50, 0x2, 0xe1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x4c,
                                0x0, 0x0, 0x0, 0x72,
                                0x4a, 0x43, 0x4, 0x21, 0x88, 0x0, 0x31, 0x0, 0x0, 0x81, 0x4c,
                                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5d,
                                0x80, 0x1, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x42, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

//                        String ori = "0000004a000100010000008246484d5002e1010100000047000000724a430421880031000081470000000000000000005d8001ffffff000000010009000000000001ffffffffffff000000420000000100000000ffff00000000000000010000002c0000000000000002000000020000000001010100000000000000000000040000000001010100000000000000";
//                        ori.length(); //142
                        ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
                        for (int i = 0; i < bytes.length; i++) {
                            if (i == 23 || i == 38) {
                                buffer.put(sno);
                            }
                            else {
                                buffer.put((byte) bytes[i]);
                            }
                        }
                        buffer.flip();
                        byte[] sendData = buffer.array();
                        // fos 28
                        // 协议头21字节
                        // 15字节
                        //byte[] sendData = cArrayStringToByteArray(cArrayString);
                        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, targetAddress, PORT);
                        socket.send(sendPacket);
                        System.out.println("数据已发送");

                        // 接收数据
                        byte[] receiveData = new byte[BUFFER_SIZE];
                        DatagramPacket receivePacket = new DatagramPacket(receiveData, BUFFER_SIZE);
                        try {
                            socket.receive(receivePacket);
                            System.out.println("接收到的数据长度: " + receivePacket.getLength());
                            // 收到数据改变网元网络状态
                            // 接收到数据，0 网元离线 灰色；1：告警 红；2：正常 绿色；

                            // 数据头长度
                            int headerLen = 28 + 21 + 21;
                            // source ip
                            InetAddress sourceAddress = receivePacket.getAddress();
                            String sourceIp = sourceAddress.getHostAddress();
                            // 接收到的数据长度
                            int dataLen = receivePacket.getLength();
                            // 处理接收到的数据
                            byte[] receivedBytes = receivePacket.getData();
                            if (sourceIp.equals(TARGET_IP) && dataLen >  headerLen) {
                                // 判断是否JC0422 【28,29，30,31】、报警数据【64,65】
                                if (receivedBytes[28] == (byte) 0x4a
                                        && receivedBytes[29] == (byte) 0x43
                                        && receivedBytes[30] == (byte) 0x04
                                        && receivedBytes[31] == (byte) 0x22
                                        && receivedBytes[64] == (byte) 0x00
                                        && receivedBytes[65] == (byte) 0x0d) {

                                    // 处理接收到的数据
                                    byte[] rData = new byte[dataLen - headerLen];
//从PB数据开始
                                    System.arraycopy(receivedBytes, headerLen, rData, 0, dataLen - headerLen);
                                    Alarm.NeAlarmHead neAlarmHead = Alarm.NeAlarmHead.parseFrom(rData);
                                    System.out.println(neAlarmHead);



                                    // 告警解析入库
                                    List<ElementAlarm> elementAlarmList = new ArrayList<>();
                                    List<Alarm.AlarmItem> itemList = neAlarmHead.getBrdAlrm(0).getArmVectorList();
                                    for (Alarm.AlarmItem alarmItem : itemList) {
                                        ElementAlarm elementAlarm = new ElementAlarm();
                                        elementAlarm.setId(IdUtils.simpleUUID());
//                                        elementAlarm.setElementId(elementId);
//                                        elementAlarm.setName(elementName);
                                        int alarmCode = alarmItem.getArmValue(0).getCode();
                                        String strAlarmCode = "未知";
                                        if (alarmCode == 2163) {
                                            strAlarmCode = "输入光信号丢失(RLOS)";
                                        }
                                        else if (alarmCode == 1753) {
                                            strAlarmCode = "光模块不在位(OTRX_ABSENT)";
                                        }
                                        else if (alarmCode == 3054) {
                                            strAlarmCode = "配置未保存(CFG NOT SAVE)";
                                        }
                                        else if (alarmCode == 795) {
                                            strAlarmCode = "输入光功率过低(IOP LOW)";
                                        }
                                        elementAlarm.setAlarmCode(strAlarmCode); // 告警代码
                                        // 告警类别
                                        elementAlarm.setAlarmType("设备告警");
                                        // 附加信息
                                        elementAlarm.setAddition(alarmItem.getLine().getNetworkCrossString());
                                        elementAlarm.setLineNo(alarmItem.getLine().getTag() + ":" + alarmItem.getLine().getLocateSrcString() + ""); // 线路号
                                        elementAlarm.setIp(sourceIp);
                                        elementAlarm.setProjectStatus(alarmItem.getArmValue(0).getStatus() + ""); // 告警状态
                                        elementAlarm.setCreateBy("admin");
                                        elementAlarm.setCreateTime(new Date(alarmItem.getArmValue(0).getTime()));
                                        elementAlarmList.add(elementAlarm);
                                    }
                                    if (elementAlarmList.size() > 0) {
//                                        elementAlarmService.insertElementAlarms(elementAlarmList);
                                    }
                                }
                            }
                           /* for (int i = 0; i < dataLen; i++) {

                                System.out.print((char) receivedBytes[i]);
                            }*/
                        } catch (Exception e) {
                            System.out.println("接收数据超时或出现异常: " + e.getMessage());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, 0, POLLING_INTERVAL);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}